package com.ethink.platform.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ethink.framework.common.constant.CommonRespCode;
import com.ethink.framework.common.exception.BusinessException;
import com.ethink.framework.common.web.context.SPRequestContextHolder;
import com.ethink.mdm.api.MateFacade;
import com.ethink.mdm.api.info.MateSkuInfo;
import com.ethink.order.api.TocSaleAfterImportLogFacade;
import com.ethink.order.api.enums.TocSaleAfterImportLogOrderStatusEnum;
import com.ethink.order.api.enums.TocSaleAfterImportLogOrderTypeEnum;
import com.ethink.order.api.info.SaleOrderInfo;
import com.ethink.order.api.info.TocSaleAfterImportLogDetailInfo;
import com.ethink.order.api.model.SaleDetailOrderModel;
import com.ethink.order.api.model.TocSaleAfterExcelOfficeModel;
import com.ethink.order.api.model.TocSaleAfterExcelWarehouseModel;
import com.ethink.order.api.request.UpdateStatusBaseRequest;
import com.ethink.order.api.response.SaleOrderDetailResponse;
import com.ethink.order.api.response.TocSaleAfterImportResponse;
import com.ethink.platform.controller.order.info.TocSaleAfterImportInfo;
import com.ethink.warehouse.api.MateInventoryFacade;
import com.ethink.warehouse.api.MateProduceCodeFacade;
import com.ethink.warehouse.api.SubWarehouseFacade;
import com.ethink.warehouse.api.enums.MateInventoryOrderBizTypeEnum;
import com.ethink.warehouse.api.enums.SubjectEnum;
import com.ethink.warehouse.api.info.MateProduceCodeInfo;
import com.ethink.warehouse.api.info.SubWarehouseInfo;
import com.ethink.warehouse.api.request.MateInventoryOrderAddT51OrT91Request;
import com.ethink.warehouse.api.request.MateInventoryOrderAddT51OrT91RequestItem;
import com.ethink.warehouse.api.request.MateProduceCodeQueryRequest;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author default
 * @version 1.0.0
 * @ClassName TocSaleAfterManager.java
 * @Description
 * @createTime 2023年01月15日 20:59:00
 */
@Component
public class TocSaleAfterManager {

    @Autowired
    private ExcelImportManager excelImportManager;

    @Autowired
    private MateFacade mateFacade;

    @Autowired
    private SubWarehouseFacade subWarehouseFacade;

    @Autowired
    private TocSaleAfterImportLogFacade tocSaleAfterImportLogFacade;

    @Autowired
    private MateInventoryFacade mateInventoryFacade;

    @Autowired
    private MateProduceCodeFacade mateProduceCodeFacade;

    public List<TocSaleAfterImportInfo> excelImport(MultipartFile file, Integer orderType) {
        Map<String, SubWarehouseInfo> subWarehouseInfoMap = subWarehouseFacade.listSubWarehouse()
                .stream().collect(Collectors.toMap(SubWarehouseInfo::getSubWarehouseName, Function.identity()));
        //判断订单类型
        if (TocSaleAfterImportLogOrderTypeEnum.T2.eq(orderType)) {
            List<TocSaleAfterExcelOfficeModel> importModels = excelImportManager.transferClass(file, TocSaleAfterExcelOfficeModel.class);
            List<MateProduceCodeQueryRequest> requestList = new ArrayList<>();
            for (TocSaleAfterExcelOfficeModel importModel : importModels) {
                if (ObjectUtil.hasEmpty(importModel.getMateSku(), importModel.getProduceCode(), importModel.getInventoryType(), importModel.getReturnQty())) {
                    throw new BusinessException(CommonRespCode.PARAM_ERR, "办公室订单:商品编码、生产批次,库存类型,退货数量不能为空");
                }
                MateProduceCodeQueryRequest request = new MateProduceCodeQueryRequest();
                request.setMateSku(importModel.getMateSku());
                request.setProduceCode(importModel.getProduceCode());
                requestList.add(request);
            }
            Map<String, TocSaleAfterExcelOfficeModel> map = importModels.stream()
                    .collect(Collectors.toMap(a -> a.getShopOrderNo() + a.getMateSku() + a.getProduceCode() + a.getInventoryType(), Function.identity(), (v1, v2) -> v2));
            if (map.size() != importModels.size()) {
                throw new BusinessException(CommonRespCode.PARAM_ERR.getCode(), "导入数据重复");
            }
            //校验商品编码+生产批次存在
            List<MateProduceCodeInfo> mateProduceCodeInfos = mateProduceCodeFacade.skuAndProduceCodeUnionQuery(requestList);
            Set<String> mateSkuProduceCodeSet = mateProduceCodeInfos.stream()
                    .map(info -> info.getMateSku() + info.getProduceCode())
                    .collect(Collectors.toSet());
            for (TocSaleAfterExcelOfficeModel importModel : importModels) {
                if (!mateSkuProduceCodeSet.contains(importModel.getMateSku() + importModel.getProduceCode())) {
                    throw new BusinessException(CommonRespCode.PARAM_ERR.getCode(), "商品" + importModel.getMateSku() + "生产批次" + importModel.getProduceCode() + "不存在");
                }
            }
            Set<String> mateSkuSet = importModels.stream().map(a -> a.getMateSku().trim()).collect(Collectors.toSet());
            List<MateSkuInfo> mateInfoList = mateFacade.queryMateSkuBySkuCodeList(new ArrayList<>(mateSkuSet));
            if (mateInfoList.size() != mateSkuSet.size()) {
                throw new BusinessException(CommonRespCode.PARAM_ERR, "部分商品编码不存在");
            }
            Map<String, MateSkuInfo> mateSkuInfoMap = mateInfoList.stream().collect(Collectors.toMap(MateSkuInfo::getMateSku, Function.identity()));
            for (TocSaleAfterExcelOfficeModel importModel : importModels) {
                importModel.setMateSkuName(mateSkuInfoMap.get(importModel.getMateSku().trim()).getMateSkuName());
            }
            List<TocSaleAfterImportInfo> infoList = importModels.stream().map(
                    getFunction(subWarehouseInfoMap)
            ).collect(Collectors.toList());
            return infoList;
        } else if (TocSaleAfterImportLogOrderTypeEnum.T1.eq(orderType)) {
            List<TocSaleAfterExcelWarehouseModel> importModels = excelImportManager.transferClass(file, TocSaleAfterExcelWarehouseModel.class);
            List<TocSaleAfterImportInfo> infoList = importModels.stream().map(
                    getFunction(subWarehouseInfoMap)
            ).collect(Collectors.toList());
            return infoList;
        } else {
            throw new BusinessException(CommonRespCode.PARAM_ERR.getCode(), "非法请求");
        }
    }

    @NotNull
    private <T> Function<T, TocSaleAfterImportInfo> getFunction(Map<String, SubWarehouseInfo> subWarehouseInfoMap) {
        return m -> {
            TocSaleAfterImportInfo importInfo = new TocSaleAfterImportInfo();
            BeanUtil.copyProperties(m, importInfo);
            SubWarehouseInfo subWarehouseInfo = subWarehouseInfoMap.get(importInfo.getSubWarehouseName().trim());
            if (ObjectUtil.isEmpty(subWarehouseInfo)) {
                throw new BusinessException(CommonRespCode.PARAM_ERR, "仓库名称不存在: " + importInfo.getSubWarehouseName());
            }
            importInfo.setSubWarehouseCode(subWarehouseInfo.getSubWarehouseCode());
            return importInfo;
        };
    }

    private MateInventoryOrderAddT51OrT91Request t91RequestFill(String saleReturnOrderNo
            , SaleOrderDetailResponse saleOrderDetailResponse, List<TocSaleAfterImportLogDetailInfo> list, Integer orderType) {
        SaleOrderInfo main = saleOrderDetailResponse.getMain();
        TocSaleAfterImportLogDetailInfo info = list.get(0);
        MateInventoryOrderAddT51OrT91Request t91Request = new MateInventoryOrderAddT51OrT91Request();
        t91Request.setBizType(MateInventoryOrderBizTypeEnum.T4.getIntValue());
        t91Request.setBizOrderNo(saleReturnOrderNo);
        t91Request.setSourceOrderType(SubjectEnum.T51.getCode());
        t91Request.setSubject(SubjectEnum.T51.getCode());
        t91Request.setSubWarehouseCode(info.getSubWarehouseCode());
        t91Request.setCreateUserCode(SPRequestContextHolder.getCurrentSystemUserLoginName());
        t91Request.setCreateUserName(SPRequestContextHolder.getCurrentSystemUserRealName());
        List<MateInventoryOrderAddT51OrT91RequestItem> items = new ArrayList<>();
        for (SaleDetailOrderModel saleDetailOrderModel : saleOrderDetailResponse.getItem()) {
            MateInventoryOrderAddT51OrT91RequestItem item = new MateInventoryOrderAddT51OrT91RequestItem();
            item.setSourceOrderNo(saleReturnOrderNo);
            item.setSourceDetailOrderNo(saleDetailOrderModel.getDetailOrderNo());
            item.setMateSku(saleDetailOrderModel.getMateSku());
            item.setInventoryType(saleDetailOrderModel.getInventoryType());
            item.setSaleSubChannel(main.getSaleSubChannel());
            item.setPurchaseCode(saleDetailOrderModel.getPurchaseCode());
            item.setActualInQty(saleDetailOrderModel.getOutQty());
            item.setRealProduceCode(saleDetailOrderModel.getProduceCode());
            items.add(item);
        }
        t91Request.setItems(items);
        return t91Request;
    }

    public void createInventoryOrder(List<TocSaleAfterImportResponse> responseList, Long id) {
        List<MateInventoryOrderAddT51OrT91Request> requests = new ArrayList<>();
        for (TocSaleAfterImportResponse importResponse : responseList) {
            MateInventoryOrderAddT51OrT91Request t91Request = t91RequestFill(importResponse.getSaleReturnOrderNo(), importResponse.getSaleOrderDetailResponse(),
                    importResponse.getList(), importResponse.getOrderType());
            requests.add(t91Request);
        }
        mateInventoryFacade.addMateInventoryOrderAddT51OrT91(requests);
        UpdateStatusBaseRequest updateStatusBaseRequest = new UpdateStatusBaseRequest();
        updateStatusBaseRequest.setId(id);
        updateStatusBaseRequest.setOrderStatus(TocSaleAfterImportLogOrderStatusEnum.S2.getIntValue());
        tocSaleAfterImportLogFacade.updateStatus(updateStatusBaseRequest);
    }
}
